home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / basic / ace_final.lha / ACE_GPL_Release / src / APP / app.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-29  |  8.1 KB  |  370 lines

  1. /* ACE pre-processor.
  2. ** Copyright (C) 1998 David Benn
  3. ** 
  4. ** This program is free software; you can redistribute it and/or
  5. ** modify it under the terms of the GNU General Public License
  6. ** as published by the Free Software Foundation; either version 2
  7. ** of the License, or (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  
  18.    functions:     1. #INCLUDE "name"|<name> -- recursive file inclusion.
  19.         2. '..    -- single-line comment.
  20.         3. {..}    -- block comment.                    
  21.                 
  22.    Author: David J Benn
  23.      Date: 4th,5th,7th,8th July 1992,
  24.        27th,29th December 1992,
  25.        26th,30th January 1993,
  26.        2nd,6th February 1993,
  27.        24th,25th December 1993,
  28.        2nd January 1994
  29. */
  30.  
  31. #include <exec/types.h>
  32. #include <exec/memory.h>
  33. #include <libraries/dos.h>
  34. #include <stdio.h>
  35.  
  36. static char *version = "$VER: APP 1.1 (02.01.1994)";
  37.  
  38. #define MAXCHARS         80
  39.  
  40. /* exit codes */
  41. #define OK                 0
  42. #define ERR              10
  43.  
  44. /* errors */
  45. #define SRC_EQ_DEST     0
  46. #define CANT_OPEN_DEST      1
  47. #define CANT_OPEN_SRC    2
  48. #define NODE_ALLOC_ERR     3
  49. #define NAME_ALLOC_ERR     4
  50.  
  51. /* linked-list of #included files */
  52. typedef struct incl_file_list {
  53.                 char *filename;
  54.                 FILE *src;
  55.                 struct incl_file_list *next;
  56.                   } INCL;
  57.  
  58. INCL     *incl,*curr_incl,*new_incl;
  59.  
  60. FILE    *dest;
  61.  
  62. /* redefine ZC's CTRL-C testing function to do nothing! */
  63. long    Chk_Abort() { return 0; }
  64.  
  65. /* external functions */
  66. extern    void    *alloc();
  67. extern    void    free_alloc();
  68.  
  69. /* functions */
  70. void     usage();
  71. void     _error();
  72. BOOL     isalpha();
  73. void    user_break();
  74. void    preprocess();
  75. void    create_incl_list();
  76. BOOL    incl_file_exists();
  77. void    enter_incl_filename();
  78. void    kill_incl_list();
  79. void     clear_ctrl_c();
  80.  
  81. void usage()
  82. {
  83.  puts("usage: APP <source> <destination>");
  84.  exit(ERR);
  85. }
  86.  
  87. void _error(n,filename)
  88. int  n;
  89. char *filename;
  90. {
  91.  switch(n)
  92.  {
  93.   case SRC_EQ_DEST    :    puts("source and destination must be different files.");
  94.             break;
  95.  
  96.   case CANT_OPEN_DEST : printf("can't open destination file: %s\n",filename);
  97.                break;
  98.  
  99.   case CANT_OPEN_SRC  : printf("can't open source file: %s\n",filename);
  100.                break;
  101.  
  102.   case NODE_ALLOC_ERR : puts("can't allocate memory for file list node."); 
  103.                kill_incl_list();
  104.                fclose(dest);
  105.                break;
  106.  
  107.   case NAME_ALLOC_ERR : puts("can't allocate memory for file list member.");
  108.                 kill_incl_list();
  109.                fclose(dest);
  110.                break;
  111.  }
  112.  
  113.  /* clean up and exit */
  114.  free_alloc();
  115.  exit(ERR);
  116. }
  117.  
  118. void create_incl_list()
  119. {
  120.  /* create head of include file list */
  121.  
  122.  incl = (INCL *)alloc(sizeof(INCL),MEMF_PUBLIC);
  123.  if (incl == NULL) _error(NODE_ALLOC_ERR,"  ");  
  124.  else
  125.      { curr_incl = incl; incl->next = NULL; }
  126. }
  127.  
  128. BOOL incl_file_exists(name)
  129. char *name;
  130. {
  131. INCL *curr;
  132.  /* report whether an include file is
  133.     on the list.
  134.  */
  135.  
  136.  curr = incl->next;    /* start with first node after head */
  137.  
  138.  while (curr != NULL)
  139.  {
  140.   if (strcmp(curr->filename,name) == 0)
  141.      return(TRUE);
  142.   else
  143.      curr = curr->next;
  144.  }
  145.  return(FALSE);  /* name not found */
  146. }
  147.  
  148. void enter_incl_filename(name,src)
  149. char *name;
  150. FILE *src;
  151. {
  152.  /* add an include filename to the list
  153.     if it doesn't already exist.
  154.  */
  155.  
  156.  if (incl_file_exists(name)) return;    /* name is already on the list */
  157.  
  158.  /* allocate memory for a new list node */
  159.  if ((new_incl = (INCL *)alloc(sizeof(INCL),MEMF_PUBLIC))==NULL)
  160.     _error(NODE_ALLOC_ERR,"  ");
  161.  
  162.  /* allocate memory for a name in the new node */
  163.  if ((new_incl->filename = (char *)alloc(strlen(name)+1,MEMF_PUBLIC))==NULL)
  164.     _error(NAME_ALLOC_ERR,"  ");
  165.  
  166.  /* fill new node */
  167.  strcpy(new_incl->filename,name);
  168.  new_incl->src=src;
  169.  new_incl->next = NULL;
  170.  curr_incl->next = new_incl;
  171.  curr_incl = curr_incl->next;  
  172. }
  173.  
  174. void kill_incl_list()
  175. {
  176. INCL *curr,*temp;
  177. BOOL past_head=FALSE;
  178.  
  179.  /* close #included files */
  180.  
  181.  curr=incl;    /* head of list */
  182.  
  183.  do
  184.  {
  185.   temp=curr;
  186.   curr=curr->next;
  187.   if (past_head)
  188.      if (temp->src) fclose(temp->src);  /* close the file */
  189.  
  190.   if (!past_head) past_head=TRUE;
  191.  }
  192.  while (curr != NULL);  
  193. }
  194.  
  195. BOOL isalpha(ch)
  196. char ch;
  197. {
  198.  if (((ch >= 'a') && (ch <= 'z')) ||
  199.      ((ch >= 'A') && (ch <= 'Z'))) return(TRUE);
  200.  else
  201.      return(FALSE);
  202. }
  203.  
  204. void user_break()
  205. {
  206.  /* if user has hit ctrl-c, cleanup and abort. */
  207.  
  208.  if (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  209.  {
  210.      puts("*** Break: app terminating.");
  211.      kill_incl_list();
  212.      fclose(dest);
  213.      free_alloc();
  214.      exit(ERR);
  215.  }
  216. }
  217.  
  218. void preprocess(srcfile)
  219. char *srcfile;
  220. {
  221. FILE *src;
  222. char ch,buf[MAXCHARS],incl_name[MAXCHARS],incl_path[MAXCHARS+11];
  223. int  cc,i,blk_comment_lines;
  224. BOOL block_comment,command,incl_dir;
  225. BOOL inside_string_literal=FALSE;
  226.  
  227.  if (incl_file_exists(srcfile)) return;     /* file has already been included */
  228.  else
  229.  if ((src=fopen(srcfile,"r")) == NULL) 
  230.     printf("can't open %s\n",srcfile); 
  231.  else
  232.  {
  233.   enter_incl_filename(srcfile,src);  /* record this file as #included */
  234.   do
  235.   {
  236.    /* check for user break */
  237.    user_break();
  238.  
  239.    block_comment=FALSE;
  240.    command=FALSE;
  241.    incl_dir=FALSE;
  242.  
  243.    ch=fgetc(src); 
  244.  
  245.    /* single-line comment */
  246.    if (ch == '\'' && !inside_string_literal) 
  247.       while (((ch=fgetc(src)) != '\n') && (ch != EOF));
  248.    else
  249.    /* multi-line comment */
  250.    if (ch == '{' && !inside_string_literal) 
  251.    {
  252.     blk_comment_lines=0;
  253.     while (((ch=fgetc(src)) != '}') && (ch != EOF)) 
  254.           if (ch == '\n') ++blk_comment_lines;
  255.  
  256.     block_comment = TRUE;  /* don't want to copy "}" to dest file */
  257.  
  258.     /* send LF characters to dest file to keep line numbers
  259.        the same as in the source file for errors etc.
  260.     */
  261.     for (i=1;i<=blk_comment_lines;i++) fputc('\n',dest);
  262.    }
  263.    else
  264.    /* start or end of string literal? */
  265.    if (ch == '"')
  266.    {
  267.     if (!inside_string_literal) inside_string_literal = TRUE;  /* start */
  268.     else
  269.         inside_string_literal = FALSE;  /* end */    
  270.    }
  271.    else
  272.    /* pre-processor # command? */
  273.    if (ch == '#')
  274.    {
  275.     /* pre-processor command may follow */
  276.     cc=0;
  277.     do 
  278.     {
  279.      ch=fgetc(src);
  280.      if (isalpha(ch)) buf[cc++]=ch;
  281.     }
  282.     while (isalpha(ch) && (cc < MAXCHARS));
  283.  
  284.     buf[cc]='\0';
  285.     strupr(buf);
  286.  
  287.     /* legal command? */
  288.     if ((strcmp(buf,"INCLUDE") == 0) && 
  289.        ((ch == '"') || (ch == '<') || (ch == ' '))) 
  290.     {
  291.      command=TRUE;
  292.      /* get file name */
  293.      cc=0;
  294.      do 
  295.      {
  296.       /* skip whitespace */
  297.       while ((ch <= ' ') && (ch != EOF)) ch=fgetc(src); 
  298.  
  299.       /* look for file in local include directory? */
  300.       if (ch == '<') incl_dir=TRUE;
  301.  
  302.       ch=fgetc(src);
  303.       if ((ch != '"') && (ch != '>') && (ch != EOF) && 
  304.           (ch != '\n') && (cc < MAXCHARS)) incl_name[cc++]=ch;
  305.      }
  306.      while ((ch != '"') && (ch != '>') && (ch != EOF) && (ch != '\n') && 
  307.         (cc < MAXCHARS));
  308.    
  309.      /* use local include directory? */
  310.      if (incl_dir) 
  311.         strcpy(incl_path,"ACEinclude:");
  312.      else
  313.         incl_path[0]='\0';
  314.   
  315.      incl_name[cc]='\0';
  316.      strcat(incl_path,incl_name);
  317.  
  318.      preprocess(incl_path); 
  319.  
  320.      /* skip the last '"' */
  321.      ch=fgetc(src);  
  322.     }
  323.     else
  324.         fprintf(dest,"#%s",buf);  /* just copy '#' and characters */
  325.    }
  326.    
  327.    /* just copy character to dest */
  328.    if ((ch != EOF) && !command && !block_comment) fputc(ch,dest);
  329.   }
  330.   while (ch != EOF);
  331.  }
  332. }
  333.  
  334. main(argc,argv)
  335. int  argc;
  336. char *argv[];
  337. {
  338. FILE *src;
  339. int  result;
  340.  
  341.  printf("ACE preprocessor version 1.1, copyright ");
  342.  putchar(169);
  343.  printf(" 1992-1994 David Benn.\n");
  344.  
  345.  if (argc != 3) usage();
  346.  
  347.  /* are the two arguments the same? */
  348.  if (strcmp(argv[1],argv[2]) == 0) _error(SRC_EQ_DEST,"  ");
  349.  
  350.  /* test for existence of source file */
  351.  if ((src=fopen(argv[1],"r")) == NULL) _error(CANT_OPEN_SRC,argv[1]);
  352.  fclose(src);  /* this is opened again by preprocess() */
  353.  
  354.  /* try to open destination file */
  355.  if ((dest=fopen(argv[2],"w")) == NULL) _error(CANT_OPEN_DEST,argv[2]);
  356.  
  357.  open_intui_lib();
  358.  
  359.  create_incl_list();
  360.  
  361.  preprocess(argv[1]);
  362.  
  363.  kill_incl_list();
  364.  
  365.  fclose(dest);
  366.  free_alloc();
  367.  
  368.  exit(OK);
  369. }
  370.